package clock.socoolby.com.clock.widget.animatorview.animator;

import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Shader;

import java.util.ArrayList;
import java.util.List;

import static java.lang.Float.parseFloat;

import clock.socoolby.com.clock.widget.animatorview.AbstractAnimator;
import clock.socoolby.com.clock.widget.animatorview.I_AnimatorEntry;

//参考自:https://github.com/scwang90/MultiWaveHeader
public class WaterAnimator extends AbstractAnimator<WaterAnimator.Water> {


    public WaterAnimator() {
        this(1);
    }

    public WaterAnimator(int entryQuantity) {
        super(entryQuantity);
    }

    @Override
    public Water createNewEntry() {
        int startColor=Color.parseColor("#00FFFFFF");
        int waveColor=color;
        randomColorIfAble();
        return new Water(width,height,waveColor,startColor,color);
    }


    class Water implements I_AnimatorEntry {

        private Paint mPaint = new Paint();
        private Matrix mMatrix = new Matrix();
        private List<Wave> mltWave = new ArrayList<>();
        private int mWaveHeight;
        private int mStartColor;
        private int mCloseColor;
        private int mGradientAngle;
        private float mVelocity;
        private float mColorAlpha;
        private float mProgress;
        private long mLastTime = 0;
        private String tag;

        public Water(int w,int h,int color,int mStartColor,int mCloseColor) {
            mPaint.setAntiAlias(true);
            mPaint.setColor(color);
            mWaveHeight =  Util.dipToPX(context,50);
            this.mStartColor =  mStartColor;
            this.mCloseColor = mCloseColor;
            mColorAlpha = 0.45f;
            mProgress = 1f;
            mVelocity =  1f;
            mGradientAngle = 45;
            tag="70,25,1.4,1.4,-26\n" +
                        "100,5,1.4,1.2,15\n" +
                        "420,0,1.15,1,-10\n" +
                        "520,10,1.7,1.5,20\n" +
                        "220,0,1,1,-15";

            updateWavePath(w, h);
            updateLinearGradient(w, h);
        }

        public void runWave() {

        }

        private void updateLinearGradient(int width, int height) {
            //int startColor = Util.getColorWithAlpha(mStartColor, mColorAlpha*255);
            //int closeColor = Util.getColorWithAlpha(mCloseColor, mColorAlpha*255);
            //noinspection UnnecessaryLocalVariable
            //double w = width;
            //double h = height * mProgress;
            //double r = Math.sqrt(w * w + h * h) / 2;
            //double y = r * Math.sin(2 * Math.PI * mGradientAngle / 360);
            //double x = r * Math.cos(2 * Math.PI * mGradientAngle / 360);
            //mPaint.setShader(new LinearGradient((int)(w/2-x), (int)(h/2-y), (int)(w/2+x), (int)(h/2+y), startColor, closeColor, Shader.TileMode.CLAMP));

        }

        private void updateWavePath(int w, int h) {
         mltWave.clear();
        if (tag instanceof String) {
                String[] waves = tag.toString().split("\\s+");
                if ("-1".equals(tag)) {
                    waves = "70,25,1.4,1.4,-26\n100,5,1.4,1.2,15\n420,0,1.15,1,-10\n520,10,1.7,1.5,20\n220,0,1,1,-15".split("\\s+");
                } else if ("-2".equals(tag)) {
                    waves = "0,0,1,0.5,90\n90,0,1,0.5,90".split("\\s+");
                }
                for (String wave : waves) {
                    String[] args = wave.split ("\\s*,\\s*");
                    if (args.length == 5) {
                        mltWave.add(new Wave(Util.dipToPX(context,parseFloat(args[0])), Util.dipToPX(context,parseFloat(args[1])), Util.dipToPX(context,parseFloat(args[4])), parseFloat(args[2]), parseFloat(args[3]), w, h, mWaveHeight/2));
                    }
                }
            } else {
                mltWave.add(new Wave(Util.dipToPX(context,50), Util.dipToPX(context,0), Util.dipToPX(context,5), 1.7f, 2f, w, h, mWaveHeight/2));
            }

        }

        @Override
        public void move(int maxWidth, int maxHight) {
            runWave();
        }

        @Override
        public void onDraw(Canvas canvas, Paint paint) {
            if (mltWave.size() > 0 && mPaint != null) {
                long thisTime = System.currentTimeMillis();
                for (Wave wave : mltWave) {
                    mMatrix.reset();
                    canvas.save();
                    if (mLastTime > 0 && wave.velocity != 0) {
                        float offsetX = (wave.offsetX - (wave.velocity * mVelocity * (thisTime - mLastTime) / 1000f));
                        if (-wave.velocity > 0) {
                            offsetX %= wave.width / 2;
                        } else {
                            while (offsetX < 0) {
                                offsetX += (wave.width / 2);
                            }
                        }
                        wave.offsetX = offsetX;
                        mMatrix.setTranslate(offsetX, (1 - mProgress) * height);
                        canvas.translate(-offsetX, -wave.offsetY - (1 - mProgress) * height);
                    } else{
                        mMatrix.setTranslate(wave.offsetX, (1 - mProgress) * height);
                        canvas.translate(-wave.offsetX, -wave.offsetY - (1 - mProgress) * height);
                    }
                    //mPaint.getShader().setLocalMatrix(mMatrix);
                    canvas.drawPath(wave.path, mPaint);
                    canvas.restore();
                }
                mLastTime = thisTime;
            }
        }
    }

    /**
     * 水波对象
     * Created by SCWANG on 2017/12/11.
     */
    class Wave {

        Path path;          //水波路径
        int width;          //画布宽度（2倍波长）
        int wave;           //波幅（振幅）
        float offsetX;        //水波的水平偏移量
        float offsetY;        //水波的竖直偏移量
        float velocity;       //水波移动速度（像素/秒）
        private float scaleX;       //水平拉伸比例
        private float scaleY;       //竖直拉伸比例


        /**
         * 通过参数构造一个水波对象
         *
         * @param offsetX  水平偏移量
         * @param offsetY  竖直偏移量
         * @param velocity 移动速度（像素/秒）
         * @param scaleX   水平拉伸量
         * @param scaleY   竖直拉伸量
         * @param w        波长
         * @param h        画布高度
         * @param wave     波幅（波宽度）
         */

        public Wave(int offsetX, int offsetY, int velocity, float scaleX, float scaleY, int w, int h, int wave) {

            this.width = (int) (2 * scaleX * w); //画布宽度（2倍波长）
            this.wave = wave;           //波幅（波宽）
            this.scaleX = scaleX;       //水平拉伸量
            this.scaleY = scaleY;       //竖直拉伸量
            this.offsetX = offsetX;     //水平偏移量
            this.offsetY = offsetY;     //竖直偏移量
            this.velocity = velocity;   //移动速度（像素/秒）
            this.path = buildWavePath(width, h);
        }


      /*
       * 根据 波长度、中轴线高度、波幅 绘制水波路径
       */

        public void updateWavePath(int w, int h, int waveHeight) {
            this.wave = (wave > 0) ? wave : waveHeight / 2;
            this.width = (int) (2 * scaleX * w);  //画布宽度（2倍波长）
            this.path = buildWavePath(width, h);
        }


        private Path buildWavePath(int width, int height) {
            int DP = Util.dipToPX(context, 1);//一个dp在当前设备表示的像素量（水波的绘制精度设为一个dp单位）
            if (DP < 1) {
                DP = 1;
            }

            int wave = (int) (scaleY * this.wave);//计算拉伸之后的波幅

            Path path = new Path();
            //path.moveTo(0, 0);
            //path.lineTo(0, height - wave);
            path.moveTo(0, height);
            path.lineTo(0, height - wave);

            for (int x = DP; x < width; x += DP) {
                path.lineTo(x, height - wave - wave * (float) Math.sin(4.0 * Math.PI * x / width));
            }

            path.lineTo(width, height - wave);
            //path.lineTo(width, 0);
            path.lineTo(width, height);
            path.close();
            return path;
        }
    }


    /**
     * 绘制外层的刻度
     *
     * @param canvas
    protected void drawOutArc(Canvas canvas) {
        canvas.save();
        for (int i = 0; i < 100; i++) {
            if (i < mPercent) {
                mOutProgressPaint.setColor(mProgressColor);
            } else {
                mOutProgressPaint.setColor(mOutBaseColor);
            }
            canvas.rotate(3.6f, width / 2, height / 2);
            canvas.drawLine(width / 2, 0, height / 2, mDefaultLineLen, mOutProgressPaint);

        }
        canvas.restore();
    }
     */

    /**
     * 根据 最高点，获取贝塞尔曲线的 控制点
     *
     * @param startPointF  开始点
     * @param endPointF    结束点
     * @param bezierPointF 最高点
     * @return 控制点
     */
    public static Point getControlPointF(Point startPointF, Point endPointF, Point bezierPointF) {
        //B(t)=(1-t)^2P0+2t(1-t)P1+t^2P2;
        Point controlPointF = new Point(0l, 0l);
        float tmp = 0.5F;
        float t = 0.5F;
        controlPointF.setX((bezierPointF.x - tmp * tmp * startPointF.y - t * t * endPointF.y) / (2 * t * tmp));
        controlPointF.setY((bezierPointF.y- tmp * tmp * startPointF.y - t * t * endPointF.y) / (2 * t * tmp));
        return controlPointF;
    }

    public static class Point{
        public float x,y;
        public Point(float x,float y){
            this.x=x;
            this.y=y;
        }

        public void setX(float x){
            this.x=x;
        }

        public void setY(float y){
            this.y=y;
        }
    }

}
